package com.quectel.cms.controller.workorder;

import cn.hutool.core.util.StrUtil;
import com.quectel.base.tuple.Tuples;
import com.quectel.business.common.CommonBusiness;
import com.quectel.business.common.dept.DeptPersonMsgBusiness;
import com.quectel.business.common.workorder.WorkOrderBusiness;
import com.quectel.cms.controller.BaseController;
import com.quectel.cms.util.SessionHolder;
import com.quectel.constant.PushConstants;
import com.quectel.constant.core.dept.DeptPersonMsgConstants;
import com.quectel.constant.core.workorder.WorkOrderConstants;
import com.quectel.constant.core.workorder.WorkOrderLogConstants;
import com.quectel.constant.global.SystemConstants;
import com.quectel.constant.global.annotation.RequirePermissions;
import com.quectel.core.module.dept.dto.DeptPersonDto;
import com.quectel.core.module.dept.service.DeptPersonService;
import com.quectel.core.module.household.service.HouseholdService;
import com.quectel.core.module.workorder.dto.WorkOrderDto;
import com.quectel.core.module.workorder.dto.WorkOrderLogDto;
import com.quectel.core.module.workorder.service.WorkOrderLogService;
import com.quectel.core.module.workorder.service.WorkOrderService;
import com.quectel.sys.module.sys.service.SysUserService;
import com.quectel.util.common.DateUtils;
import com.quectel.util.common.Page;
import com.quectel.util.common.Request;
import com.quectel.util.common.Response;
import com.quectel.util.ex.CheckErrorException;
import com.quectel.util.redis.RedisUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.locks.Lock;

import static com.quectel.cms.constants.CmsRedisCacheConstants.PROJECT_NAME;

/**
 * @author caolu
 * @email louis.cao@quectel.com
 * @date 2021-10-19 13:06:54
 */
@RestController
@RequestMapping("workOrder")
@Tag(name = "WorkOrderController", description = "工单相关api")
public class WorkOrderController extends BaseController {
    private static final String WORK_ORDER_LOCK = PROJECT_NAME + "WORK_ORDER_LOCK:";
    @DubboReference
    private WorkOrderService workOrderService;
    @DubboReference
    private WorkOrderLogService workOrderLogService;
    @DubboReference
    private SysUserService sysUserService;
    @DubboReference
    private HouseholdService householdService;
    @DubboReference
    private DeptPersonService deptPersonService;

    @Autowired
    private WorkOrderBusiness workOrderBusiness;
    @Autowired
    private DeptPersonMsgBusiness deptPersonMsgBusiness;
    @Autowired
    private CommonBusiness commonBusiness;

    /**
     * 根据参数分页查询列表
     */
    @GetMapping("list")
    @RequirePermissions(values = "workOrder:list")
    @Operation(summary = "根据参数分页查询工单列表")
    public Response<Page<WorkOrderDto>> list(
            @Parameter(description = "从1开始的页码数") @RequestParam Integer pageNo,
            @Parameter(description = "每页多少条") @RequestParam Integer pageSize,
            @Parameter(description = "状态逗号分割") @RequestParam(required = false) String statusesStr
    ) {
        //查询列表数据
        Request request = Request.configParams(Request.parseParams(httpServletRequest));

        if (StringUtils.isNotBlank(request.getString("statusesStr"))) {
            request.getParams().put("statuses", StrUtil.splitTrim(request.getString("statusesStr"), ","));
        }

        super.fillAuthorityData(request.getParams());
        int total = workOrderService.queryTotal(request.getParams());

        List<WorkOrderDto> list = null;
        if (total > 0) {
            list = workOrderService.queryList(request.getParams());
            for (WorkOrderDto workOrderDto : list) {
                DeptPersonDto personDto = deptPersonService.selectCacheById(workOrderDto.getHandlerId());
                if (personDto != null) {
                    workOrderDto.setHandlerUsername(personDto.getName());
                }
                if (workOrderDto.getCreateTime() != null) {
                    long userTimeMills = 0L;
                    if (workOrderDto.getFinishTime() != null) {
                        userTimeMills = workOrderDto.getFinishTime().getTime() - workOrderDto.getCreateTime().getTime();
                    } else {
                        userTimeMills = System.currentTimeMillis() - workOrderDto.getCreateTime().getTime();
                    }
                    long[] summary = DateUtils.convertStr(userTimeMills, DateUtils.ConvertType.d_h_m_s);
                    workOrderDto.setUseTime(String.format("%d天%d小时%d分钟%d秒", summary[0], summary[1], summary[2], summary[3]));
                }
            }
        } else {
            list = new ArrayList<>();
        }

        Page<WorkOrderDto> page = new Page<>(request.getPageNo(), request.getPageSize(), total, list);
        return Response.<Page<WorkOrderDto>>ok().wrap(page);
    }


    /**
     * 根据id查询工单单条记录
     */
    @GetMapping("info/{id}")
    @RequirePermissions(values = "workOrder:info")
    @Operation(summary = "根据id查询工单单条记录")
    public Response<WorkOrderDto> info(@PathVariable("id") Long id) {

        WorkOrderDto workOrderDto = workOrderService.selectById(id);
        if (workOrderDto == null) {
            return Response.error("工单已被删除");
        }
        Map<String, Object> params = new HashMap<>();
        super.fillAuthorityData(params);
        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));
        if (workOrderService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        return Response.<WorkOrderDto>ok().wrap(workOrderBusiness.selectById(id));
    }

    /**
     * 创建工单
     */
    @PostMapping("save")
    @RequirePermissions(values = "workOrder:edit")
    @Operation(summary = "创建工单")
    public Response<Object> save(@RequestBody @Validated WorkOrderDto workOrderDto) {

        //填充基础数据
        fillSaveCommonData(workOrderDto);


        List<WorkOrderLogDto> logs = new ArrayList<>();
        WorkOrderLogDto initLog = new WorkOrderLogDto();
        initLog.setHandlerType(WorkOrderConstants.ORDER_HANDLER_TYPE_ADMIN);
        initLog.setHandlerId(SessionHolder.getSysUserId());
        initLog.setOrderStatus(WorkOrderConstants.ORDER_STATUS_INIT);
        initLog.setOrderDes(WorkOrderLogConstants.INIT_LOG_DESC_FUNC.apply(Tuples.of(WorkOrderConstants.ORDER_HANDLER_TYPE_ADMIN, SessionHolder.getSysUser().getUsername())));
        initLog.setCreateTime(workOrderDto.getCreateTime());
        logs.add(initLog);

        workOrderDto.setOrderSource(WorkOrderConstants.ORDER_SOURCE_ADMIN);
        workOrderDto.setSourceId(SessionHolder.getSysUserId());

        if (WorkOrderConstants.ORDER_STATUS_FORWARD.equals(workOrderDto.getStatus())) {
            DeptPersonDto deptPersonDto = deptPersonService.selectById(workOrderDto.getHandlerId());
            if (deptPersonDto == null) {
                return Response.error("员工不存在");
            }
            WorkOrderLogDto forwordLog = new WorkOrderLogDto();
            forwordLog.setHandlerType(WorkOrderConstants.ORDER_HANDLER_TYPE_DEPT_PERSON);
            forwordLog.setHandlerId(workOrderDto.getHandlerId());
            forwordLog.setOrderStatus(WorkOrderConstants.ORDER_STATUS_FORWARD);

            forwordLog.setOrderDes(WorkOrderLogConstants.FORWARD_LOG_DESC_FUNC.
                    apply(Tuples.of(WorkOrderConstants.ORDER_HANDLER_TYPE_ADMIN, SessionHolder.getSysUser().getUsername(), WorkOrderConstants.ORDER_HANDLER_TYPE_DEPT_PERSON, deptPersonDto.getName())));

            forwordLog.setCreateTime(workOrderDto.getCreateTime());
            logs.add(forwordLog);

            workOrderDto.setWorkOrderLogDtoList(logs);
            //直接指派第一次处理事件就是创建时间
            workOrderDto.setFirstHandTime(workOrderDto.getCreateTime());

            Long workOrderId = workOrderService.saveOrUpdateWorkOrderAndLog(workOrderDto);


            deptPersonMsgBusiness.pushMsg(
                    new ArrayList<>(Arrays.asList(deptPersonDto)),
                    DeptPersonMsgConstants.SourceType.WORK_ORDER_MSG,
                    workOrderId,
                    null,
                    "(指派提醒)" + commonBusiness.getAddressByVillageInfo(workOrderDto) + " " +
                            workOrderBusiness.getCategoryAndType(workOrderDto)[0] + "|" + workOrderBusiness.getCategoryAndType(workOrderDto)[1] + ",详情:" + workOrderDto.getDetail(),
                    true,
                    new PushConstants.PushType[]{PushConstants.PushType.WECHAT_OFFICIAL}
            );
        } else {
            workOrderDto.setStatus(WorkOrderConstants.ORDER_STATUS_INIT);
            workOrderDto.setHandlerId(null);
            workOrderDto.setWorkOrderLogDtoList(logs);
            workOrderService.saveOrUpdateWorkOrderAndLog(workOrderDto);
        }

        return Response.ok();
    }

    /**
     * 修改工单单条记录
     */
    @PostMapping("update")
    @RequirePermissions(values = "workOrder:edit")
    @Operation(summary = "修改工单单条记录")
    public Response<Object> update(@RequestBody @Validated WorkOrderDto workOrderDto) {

        if (workOrderService
                .queryTotal(super.fillAuthorityData(new HashMap<String, Object>() {{
                    put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(workOrderDto.getId()));
                }})) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        //填充基础数据
        fillEditCommonData(workOrderDto);

        Date now = new Date();
        WorkOrderDto dbValue = workOrderService.selectById(workOrderDto.getId());
        Lock spinLock = RedisUtils.getSpinLock("WORK_ORDER_LOCK" + dbValue.getId());
        spinLock.lock();
        try {
            if (WorkOrderConstants.ORDER_STATUS_HANDLING.equals(workOrderDto.getStatus())) {
//                if (!WorkOrderConstants.ORDER_STATUS_INIT.equals(dbValue.getStatus())) {
//                    //只有初始化才可以接单
//                    return Response.error("只有未分配的订单可以接单");
//                }
//                List<WorkOrderLogDto> logs = new ArrayList<>();
//                WorkOrderLogDto log = new WorkOrderLogDto();
//                log.setHandlerId(SessionHolder.getSysUserId());
//                log.setOrderStatus(WorkOrderConstants.ORDER_STATUS_HANDLING);
//                log.setOrderDes("由管理员:" + SessionHolder.getSysUser().getUsername() + " 接单");
//                log.setOrderDes(WorkOrderLogConstants.HANDLING_LOG_DESC_FUNC.
//                        apply(Tuples.of(WorkOrderConstants.ORDER_HANDLER_TYPE_ADMIN, SessionHolder.getSysUser().getUsername())));
//                log.setCreateTime(now);
//                logs.add(log);
//
//                if (dbValue.getFirstHandTime() == null) {
//                    //没有首次服务事件设置当前时间为首次接单时间
//                    workOrderDto.setFirstHandTime(now);
//                }
//                workOrderDto.setHandlerId(SessionHolder.getSysUserId());
//                workOrderDto.setWorkOrderLogDtoList(logs);
//                workOrderService.saveOrUpdateWorkOrderAndLog(workOrderDto);


            } else if (WorkOrderConstants.ORDER_STATUS_FORWARD.equals(workOrderDto.getStatus())) {

                if (!WorkOrderConstants.ORDER_STATUS_INIT.equals(dbValue.getStatus())
                ) {
                    //只能指派未接单的工单
                    return Response.error("只能指派未接单的工单");
                }

                DeptPersonDto deptPersonDto = deptPersonService.selectCacheById(workOrderDto.getHandlerId());
                if (deptPersonDto == null) {
                    return Response.error("员工不存在");
                }

                List<WorkOrderLogDto> logs = new ArrayList<>();
                WorkOrderLogDto log = new WorkOrderLogDto();
                log.setHandlerType(WorkOrderConstants.ORDER_HANDLER_TYPE_DEPT_PERSON);
                log.setHandlerId(workOrderDto.getHandlerId());
                log.setOrderStatus(WorkOrderConstants.ORDER_STATUS_FORWARD);
                log.setOrderDes(WorkOrderLogConstants.FORWARD_LOG_DESC_FUNC.
                        apply(Tuples.of(WorkOrderConstants.ORDER_HANDLER_TYPE_ADMIN, SessionHolder.getSysUser().getUsername(), WorkOrderConstants.ORDER_HANDLER_TYPE_DEPT_PERSON, deptPersonDto.getName())));
                log.setCreateTime(now);
                logs.add(log);

                if (dbValue.getFirstHandTime() == null) {
                    //没有首次服务事件设置当前时间为首次接单时间
                    workOrderDto.setFirstHandTime(now);
                }
                workOrderDto.setHandlerId(workOrderDto.getHandlerId());
                workOrderDto.setWorkOrderLogDtoList(logs);
                Long workOrderId = workOrderService.saveOrUpdateWorkOrderAndLog(workOrderDto);

                deptPersonMsgBusiness.pushMsg(
                        new ArrayList<>(Arrays.asList(deptPersonDto)),
                        DeptPersonMsgConstants.SourceType.WORK_ORDER_MSG,
                        workOrderId,
                        null,
                        "(指派提醒)" + commonBusiness.getAddressByVillageInfo(workOrderDto) + " " +
                                workOrderBusiness.getCategoryAndType(workOrderDto)[0] + "|" + workOrderBusiness.getCategoryAndType(workOrderDto)[1] + ",详情:" + workOrderDto.getDetail(),
                        true,
                        new PushConstants.PushType[]{PushConstants.PushType.WECHAT_OFFICIAL}
                );

            } else if (WorkOrderConstants.ORDER_STATUS_FINISHED.equals(workOrderDto.getStatus())) {
//                if (
//                        WorkOrderConstants.ORDER_STATUS_FINISHED.equals(dbValue.getStatus())
//                ) {
//                    //已完成的不可以完成
//                    return Response.error("已完成的工单无法重新完成");
//                }
//                if (!Objects.equals(dbValue.getHandlerId(), SessionHolder.getSysUserId()) && !SysConstants.SYS_TOP_GROUP_CODE.equals(SessionHolder.getSysUser().getGroupCode())) {
//                    //只有自己可以处理自己的订单(该租户下的超管也是可以的)
//                    return Response.error("只可以处理当前处理人为自己的工单(超管除外)");
//                }
//                List<WorkOrderLogDto> logs = new ArrayList<>();
//                WorkOrderLogDto log = new WorkOrderLogDto();
//                log.setHandlerId(SessionHolder.getSysUserId());
//                log.setOrderStatus(WorkOrderConstants.ORDER_STATUS_FINISHED);
//                log.setOrderDes(WorkOrderLogConstants.FINISH_LOG_DESC_FUNC.
//                        apply(Tuples.of(WorkOrderConstants.ORDER_HANDLER_TYPE_ADMIN, SessionHolder.getSysUser().getUsername(), workOrderDto.getCompleteRemark())));
//                log.setCreateTime(now);
//                logs.add(log);
//
//                if (dbValue.getFirstHandTime() == null) {
//                    //没有首次服务事件设置当前时间为首次接单时间
//                    workOrderDto.setFirstHandTime(now);
//                }
//                workOrderDto.setHandlerId(SessionHolder.getSysUserId());
//                workOrderDto.setFinishTime(now);
//                workOrderDto.setWorkOrderLogDtoList(logs);
//                workOrderService.saveOrUpdateWorkOrderAndLog(workOrderDto);

            }
            return Response.ok();
        } catch (Exception e) {
            throw new CheckErrorException(e);
        } finally {
            spinLock.unlock();
        }

    }

//    /**
//     * 删除
//     */
//    @PostMapping("delete")
//    @RequirePermissions(values = "workOrder:delete")
//    @Operation(summary = "批量删除记录")
//    public Response<Object> delete(@RequestBody Long[] ids) {
//
//        for (Long id : ids) {
//            if (workOrderService
//                    .queryTotal(super.fillAuthorityData(new HashMap<String, Object>() {{
//                        put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));
//                    }})) <= 0) {
//                return Response.error(SystemConstants.ILLEGAL_MSG);
//            }
//        }
//
//        workOrderService.deleteBatch(ids);
//
//        return Response.ok();
//    }
}
